﻿using System;
using System.Threading;
using Microsoft.TeamFoundation.Client;

namespace TShooter.TfsSearch.EngineModel
{
    public abstract class EngineBase<C, I>: IEngine
        where C : ICrawler, new()
        where I : IIndexer, new()
    {
        #region Constructors and member variables

        private readonly string _Name;
        private readonly string _TypeName;
        private readonly C _Crawler = new C();
        private readonly I _Indexer = new I();
        private IService _CurrentService;
        private TeamFoundationServer _Server;
        private ThreadPriority _Priority;

        protected EngineBase(string name, string typeName)
        {
            _Name = name;
            _TypeName = typeName;
            _Crawler.Engine = this;
            _Crawler.Finished += Service_Finished;
            _Indexer.Engine = this;
            _Indexer.Finished += Service_Finished;
        }

        #endregion

        #region IService Members

        public ThreadPriority Priority
        {
            get { return _Priority; }
            set
            {
                _Priority = value;
                _Indexer.Priority = value;
                _Crawler.Priority = value;
            }
        }

        #endregion

        #region Event Handlers

        void Service_Finished(object sender, EventArgs e)
        {
            _CurrentService.Stop();

            if (_CurrentService == (IService) _Crawler)
            {
                ActivateService(_Indexer);
            }
            else
            {
                Stop();
            }
        }

        #endregion

        #region IEngine members

        public event EventHandler Finished;

        public string Name
        {
            get { return _Name; }
        }

        public string TypeName
        {
            get { return _TypeName; }
        }

        public ICrawler Crawler
        {
            get { return _Crawler; }
        }

        public IIndexer Indexer
        {
            get { return _Indexer; }
        }

        #region IEngine Members

        public TeamFoundationServer Server
        {
            get { return _Server; }
            set { _Server = value; }
        }

        #endregion

        public bool IsActive
        {
            get { return _CurrentService == null? false: _CurrentService.IsActive; }
        }

        public void Start()
        {
            if (_CurrentService == null)
            {
                ActivateService(_Crawler);
            }
            _CurrentService.Start();
        }

        public void Stop()
        {
            if (_CurrentService != null)
            {
                _CurrentService.Stop();
            }
            lock (this)
            {
                _CurrentService = null;
            }
            OnFinished();
        }

        public void Pause(int autoResumeMillisecs)
        {
            if (_CurrentService != null)
            {
                _CurrentService.Pause(autoResumeMillisecs);
            }
        }

        public void Resume()
        {
            if (_CurrentService != null)
            {
                _CurrentService.Resume();
            }
        }

        #endregion

        #region Private methods

        private void ActivateService(IService service)
        {
            lock (this)
            {
                _CurrentService = service;
                _CurrentService.Start();
            }
        }

        protected virtual void OnFinished()
        {
            if (Finished != null)
            {
                Finished(this, EventArgs.Empty);
            }
        }

        #endregion
    }
}
